<?php
namespace app\index\controller;

use app\common\model\AlipayOrders;
use app\common\model\Software as SoftwareModel;
use Exception;
use think\facade\App;
use think\facade\Config;
use think\facade\Cookie;
use think\facade\Request;
use think\facade\Route;
use think\facade\Validate;
use Yansongda\Pay\Pay;

/**
 * 支付宝支付
 * @package app\index\controller
 * @author jwj <jwjbjg@gmail.com>
 * @copyright jwj
 */
class Alipay
{
    /**
     * 生成支付订单
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function index()
    {
        $config = Config::get('alipay');

        $out_trade_no = Request::cookie('out_trade_no');
        if (!empty($out_trade_no)) {
            $orders = AlipayOrders::findOutTradeNo($out_trade_no);
            if (null !== $orders) {
                switch ($orders['status']) {
                    case 0:
                        if (strtotime($orders['expire_time']) - time() > 300) {
                            if (Validate::checkRule(Request::param('phone'), 'mobile')) {
                                $orders->save(['phone' => Request::param('phone')]);
                            }
                            return json([
                                'code' => 0,
                                'msg'  => '已查询到尚未完成的订单',
                                'data' => [
                                    'out_trade_no' => $orders['out_trade_no'],
                                    'qr_code'      => $orders['qr_code'],
                                    'money'        => $orders['money'],
                                ]
                            ]);
                        }
                        break;
                    case 1:
                        if (strtotime($orders['create_time']) + 86400 * 7 > time()) {
                            return json([
                                'code' => 1,
                                'msg'  => '已支付，无需重新支付，请刷新网页',
                                'data' => $orders,
                            ]);
                        }
                        break;
                }
            }
        }

        try {
            $orders = AlipayOrders::create([
                'money'       => 1.00,
                'ip'          => Request::server('HTTP_X_FORWARDED_FOR', Request::ip()),
                'expire_time' => date('Y-m-d H:i:s', time() + $config['timeout'] * 60),
                'remark'      => '支付订单生成成功',
            ]);
            Pay::config(Config::get('pay'));
            $response = Pay::alipay()->scan($param = [
                'out_trade_no' => $orders['out_trade_no'],
                'total_amount' => $orders['money'],
                'subject'      => '下载加速特权',
                'body'         => SoftwareModel::where('id', Request::param('software_id'))->value('name'),
                '_notify_url'   => (string)Route::buildUrl('Alipay/notify')->domain(true),
                '_return_url'   => (string)Route::buildUrl('Alipay/return')->domain(true),
            ]);

            if (10000 != $response->code) {
                throw new Exception('支付网关[' . $response->sub_code . ']:' . $response->sub_msg);
            }

            $orders->save(['qr_code' => $response->qr_code, 'remark' => '获取支付码成功']);

        } catch (Exception $e) {
            isset($orders) && $orders->save(['status' => 2, 'remark' => $e->getMessage()]);

            return json([
                'code' => 1,
                'msg'  => $e->getMessage(),
                'line' => $e->getLine(),
                'file' => $e->getFile(),
            ]);
        }

        Cookie::set('out_trade_no', $orders['out_trade_no'], 86400);

        return json([
            'code' => 0,
            'msg'  => '订单生成成功',
            'data' => [
                'out_trade_no' => $orders['out_trade_no'],
                'qr_code'      => $orders['qr_code'],
                'money'        => $orders['money'],
            ]
        ]);
    }

    /**
     * 回调通知
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function notify()
    {
        if (Request::isGet()) {
            $data = json_decode(file_get_contents('alipay-20220701221402-25315.json'), true);
        } else {
            Pay::config(Config::get('pay'));
            $data = Pay::alipay()->callback();
            if (App::isDebug()) {
                file_put_contents('alipay-' . date('YmdHis')  . '-' . mt_rand(10000, 99999) . '.json', json_encode($data));
            }
        }

        $orders = AlipayOrders::findOutTradeNo($data['out_trade_no']);
        if (null === $orders) {
            return '商户订单未找到';
        }

        if ($orders['money'] != $data['total_amount']) {
            return '支付订单金额与通知金额不一致';
        }

        switch ($data['trade_status']) {
            // 交易完成，不可退款
            case 'TRADE_FINISHED':
                $orders->save(['remark' => '交易完成，不可退款',]);
                break;
            // 交易支付成功
            case 'TRADE_SUCCESS':
                if (1 == $orders['status']) {
                    return 'success';
                }

                $orders->save([
                    'status'         => 1,
                    'trade_no'       => $data['trade_no'],
                    'buyer_id'       => $data['buyer_id'] ?? '',
                    'buyer_logon_id' => $data['buyer_logon_id'] ?? '',
                    'remark'         => '交易支付成功',
                ]);
                break;
            // 未付款交易超时关闭，或支付完成后全额退款
            case 'TRADE_CLOSED':
                if (2 == $orders['status']) {
                    return 'success';
                }

                $orders->save([
                    'status'   => 2,
                    'trade_no' => $data['out_trade_no'],
                    'remark'   => '未付款交易超时关闭',
                ]);
                break;
        }

        return 'success';
    }

    /**
     * 检查订单支付状态
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function checkStatus()
    {
        if (!Request::has('id', 'param', true)) {
            return json([
                'code' => 1,
                'msg'  => '请输入订单号',
            ]);
        }

        $orders = AlipayOrders::findOutTradeNo(Request::param('id'));
        if (null === $orders) {
            return json([
                'code' => 1,
                'msg'  => '未找到该订单',
            ]);
        }

        switch ($orders['status']) {
            case 0:
                return json([
                    'code' => 1,
                    'msg'  => '该订单尚未支付',
                    'out_trade_no' => $orders['out_trade_no']
                ]);
                break;
            case 1:
                if (strtotime($orders['create_time']) + 86400 * 7 > time()) {
                    Cookie::set('out_trade_no', $orders['out_trade_no'], 86400);
                    return json([
                        'code' => 0,
                        'msg'  => '订单已支付'
                    ]);
                } else {
                    return json([
                        'code' => 1,
                        'msg'  => '订单已失效，请重新支付'
                    ]);
                }
                break;
            case 2:
                return json([
                    'code' => 1,
                    'msg'  => '订单已取消'
                ]);
                break;
        }
    }
}